#include<iostream>
#include<mysql/mysql.h>
#include<jsoncpp/json/json.h>
#include<string>
#include<cstdlib>
#include<mutex>
using namespace std;

#define HOST "192.168.35.143"
#define NAME "OrderSystem"
#define USER "root"
#define PASS ""

//初始化
MYSQL* OrderMysqlInit(){
  //初始化
  MYSQL* mysql = mysql_init(NULL);
  if(mysql == NULL){
    cout <<"init mysql handler failed" <<endl;
    return NULL;
  }
  //连接服务器
  if(mysql_real_connect(mysql,HOST, USER, PASS, NAME, 0, NULL ,0) == NULL){
    cout << "connect mysql server failed:" << mysql_error(mysql) << endl;
    mysql_close(mysql);//初始化失败直接退出进程---要释放资源
    return NULL;
  }
  //设置字符集
  if(mysql_set_character_set(mysql,"utf8") != 0){
    cout << "set mysql character failed:" << mysql_error(mysql) << endl;
    mysql_close(mysql);
      return NULL;
  }
  return mysql;
}

//销毁
void OrderMysqlDestory(MYSQL* mysql){
  if(mysql != NULL)
    mysql_close(mysql);
}

//执行sql
bool OrderMysqlQuery(MYSQL* mysql, const string& sql){
  if(mysql_query(mysql,sql.c_str())!= 0){
    cout << sql << endl;
    cout << "query failed:" << mysql_error(mysql) << endl;
    return false;
  }
  return true;
}

class TableOrder{
  public:
    TableOrder() :_mysql(NULL){
      _mysql = OrderMysqlInit();
      if(_mysql == NULL)
        exit(-1);
    }

    ~TableOrder(){
      if(_mysql != NULL)
        OrderMysqlDestory(_mysql);
    }

    //增加新订单(只需要传入订单信息)
    //订单信息是个Json序列化后的字符串
    bool OrderInsert(const Json::Value& order){
      if(Check(order) == false)
        return false;
      //"insert Ord values(null, '%s', 0, now(), now());" 
#define INSERT_ORD "insert Ord values(null, '%s', 0, now(), now());"
      char sql[4096] = { 0 };
      //拓展--允许传入的菜品信息是一个数组， 如[1,2]
      Json::FastWriter writer;
      string str;
      if(order["dishes"].isArray()){
        str = writer.write(order["dishes"]);
        cout << "数组序列化后：" << str << endl;
      }
      else{
        str = order["dishes"].asString();
        cout << "正常解析：" << str << endl;
      }
      //序列化之后会自动加一个换行，这里进行处理
     // if(str[str.size() - 1] == '\n')
     //   str[str.size() - 1] = '\0';
      sprintf(sql, INSERT_ORD, str.c_str());
      return OrderMysqlQuery(_mysql,sql);
    }

    //删除订单（root)
    bool OrderDelete(int order_id){
      if(order_id <= 0){
        cout << "not this id" << endl;
        return false;
      }
#define DELETE_ORD "delete from Ord where id=%d;"
      char sql[4096] = { 0 };
      sprintf(sql,DELETE_ORD,order_id);
      return OrderMysqlQuery(_mysql, sql);
    }

    //根据id修改订单状态
    bool OrderUpdate(int order_id, const Json::Value& order){
      if(order_id <= 0){
        cout << "not this id" << endl;
        return false;
      }
      //"update Ord set status=%d, mtime=now() where id=%d;"
#define UPDATE_ORD "update Ord set status=%d, mtime=now() where id=%d;"
      char sql[4096] = { 0 };
      sprintf(sql, UPDATE_ORD,order["status"].asInt(), order_id);
      return OrderMysqlQuery(_mysql,sql);
    }

    //查找订单（ALL）
    bool OrderGetAll(Json::Value* orders){
#define GET_ALL_ORD "select * from Ord;"
      char sql[4096] = { 0 };
      sprintf(sql, GET_ALL_ORD);
      //线程安全
      _mutex.lock();
      bool ret = OrderMysqlQuery(_mysql, sql);
      if(ret == false){
        _mutex.unlock();
        return false;//不需要关闭接口
      }

      MYSQL_RES* res = mysql_store_result(_mysql);
      if(res == NULL){
        _mutex.unlock();
        cout << "store result failed:" << mysql_error(_mysql) << endl;
        return false;
      }
      _mutex.unlock();

      int new_row = mysql_num_rows(res);
      if(new_row < 1){
          cout << "no order" << endl;
          return false;
      }
      int nuw_col = mysql_num_fields(res);
      for(int i = 0; i < new_row; i++){
        MYSQL_ROW row = mysql_fetch_row(res);     
        Json::Value order;
        order["id"] = atoi(row[0]);
        order["dishes"] = row[1];
        order["status"] = atoi(row[2]);
        order["ctime"] = row[3];
        order["mtime"] = row[4];
        orders->append(order);
      }
      mysql_free_result(res);
      return true;
    }

    //查找订单(ONE)
    bool OrderGetOne(int order_id, Json::Value* order){
#define GET_ONE_ORD "select dishes,status,ctime,mtime from Ord where id=%d;"
      char sql[4096] = { 0 };
      sprintf(sql, GET_ONE_ORD, order_id);
      _mutex.lock();
      bool ret = OrderMysqlQuery(_mysql, sql);
      if(ret == false){
        _mutex.unlock();
        return false;
      }
      MYSQL_RES* res = mysql_store_result(_mysql);
      if(res == NULL){
        cout << "store result failed:" << mysql_error(_mysql) << endl;
        _mutex.unlock();
        return false;
      }
      _mutex.unlock();
      int num_row = mysql_num_rows(res);
      if(num_row < 1){
        cout << "have no this order" << endl;
        return false;
      }
      MYSQL_ROW row = mysql_fetch_row(res);
      (*order)["id"] = order_id;                   
      (*order)["dishes"] = row[0];                       
      (*order)["status"] = atoi(row[1]);                
      (*order)["ctime"] = row[2];                       
      (*order)["mtime"] = row[3];  
      mysql_free_result(res);
      return true;
    }
  
  private:
    bool Check(const Json::Value& order){
      //如果传入信息是数组序列化后的，就不能用asString，因此加上IsArray判断，如果是数组，则只判断empty,不是数组才判断asString
      if(order["dishes"].empty() == true || (order["dishes"].isArray() == false && order["dishes"].asString().size() == 0)){
        cout << "new order dishes is not exists!" << endl;
        return false;
      }
      return true;
    }
  private:
    MYSQL* _mysql;
    mutex _mutex;
};
